package com.gandong8.trace.tool.domain;

import com.gandong8.trace.tool.exception.GlobalException;
import com.gandong8.trace.tool.util.JsonUtil;
import com.gandong8.trace.tool.util.TraceUtil;
import lombok.Getter;

import java.util.HashMap;
import java.util.Map;

@Getter
public class RequestData {
    private String url;
    private int retryNum = 0;
    private int retryTime = 100;
    private int socketTimeout = 5000;
    private int connectTimeout = 3000;
    private Map<String, String> headers = new HashMap<>();
    private boolean redirectsEnabled = false;
    private Map<String, String> postParams;
    private String postJson;
    private boolean https = false;
    private boolean isGet = true;
    private boolean trace = true;

    public RequestData(String url) {
        this.url = url;
        this.init();
    }

    public RequestData(String url, int socketTimeout, int connectTimeout) {
        this.url = url;
        this.socketTimeout = socketTimeout;
        this.connectTimeout = connectTimeout;
        this.init();
    }

    public RequestData setTrace(boolean trace) {
        this.trace = trace;
        if(trace) {
            setTraceId();
        } else {
            removeTraceId();
        }
        return this;
    }

    public RequestData setGetParams(Map<String,Object> getParams) {
        this.url = mapToUrl(this.url, getParams);
        return this;
    }

    public RequestData setRetryNumAndTime(Integer retryNum, Integer sleepTime) {
        this.retryNum = retryNum;
        this.retryTime = sleepTime;
        return this;
    }

    public RequestData setTimeout(Integer socketTimeout, Integer connectTimeout) {
        this.socketTimeout = socketTimeout;
        this.connectTimeout = connectTimeout;
        return this;
    }

    public RequestData setPostParams(Map<String, String> postParams) {
        postParams.forEach(this::setPostParam);
        return this;
    }

    public RequestData setPostParam(String key, String value) {
        if(this.postParams == null) {
            this.postParams = new HashMap<>();
            this.isGet = false;
        }
        this.postParams.put(key, value);
        return this;
    }

    public RequestData setPostJson(String json) {
        this.postJson = json;
        this.isGet = false;
        return this;
    }

    public RequestData setPostObject(Object postObj) {
        return setPostJson(JsonUtil.toStr(postObj));
    }

    public RequestData setHeader(String key, String value) {
        if(this.trace && key.equals(TraceUtil.TRACE_TAG)) {
            throw new GlobalException("链路标志冲突");
        }
        this.headers.put(key, value);
        return this;
    }

    public RequestData setHeaders(Map<String, String> headers) {
        headers.forEach(this::setHeader);
        return this;
    }


    private String mapToUrl(String url, Map<String, Object> paramsMap) {
        if(paramsMap == null) {
            return url;
        }
        url += url.contains("?") ? "&":"?";
        int count = 0;
        StringBuilder urlBuilder = new StringBuilder(url);
        for(Map.Entry<String, Object> entry: paramsMap.entrySet()) {
            if(count > 0) {
                urlBuilder.append("&");
            }
            urlBuilder.append(entry.getKey()).append("=").append(entry.getValue());
            count++ ;
        }
        url = urlBuilder.toString();
        return url;
    }


    private void init() {
        this.https = this.url.toLowerCase().contains("https");
        if(this.trace) {
            setTraceId();
        }
    }

    private void setTraceId() {
        headers.put(TraceUtil.TRACE_TAG, TraceUtil.getTraceId());
    }

    private void removeTraceId() {
        headers.remove(TraceUtil.TRACE_TAG);
    }

    @Override
    public String toString() {
        return "url" + "=" + url + ";" +
                "retryNum" + "=" + retryNum + ";" +
                "retryTime" + "=" + retryTime + ";" +
                "socketTimeout" + "=" + socketTimeout + ";" +
                "connectTimeout" + "=" + connectTimeout + ";" +
                "headers" + "=" + headers + ";" +
                "postParams" + "=" + postParams + ";" +
                "postJson" + "=" + postJson + ";";
    }

}
